<template>
  <div class="role-management">
    <!-- 搜索区域 -->
    <el-card class="search-card">
      <el-form
        ref="queryFormRef"
        :model="queryForm"
        :inline="true"
        label-width="80px"
      >
        <el-form-item label="角色名称" prop="roleName">
          <el-input
            v-model="queryForm.roleName"
            placeholder="请输入角色名称"
            clearable
            style="width: 200px"
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="权限字符" prop="roleKey">
          <el-input
            v-model="queryForm.roleKey"
            placeholder="请输入权限字符"
            clearable
            style="width: 200px"
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select
            v-model="queryForm.status"
            placeholder="角色状态"
            clearable
            style="width: 200px"
          >
            <el-option label="正常" value="0" />
            <el-option label="停用" value="1" />
          </el-select>
        </el-form-item>
        <el-form-item label="创建时间" style="width: 308px">
          <el-date-picker
            v-model="dateRange"
            type="daterange"
            range-separator="-"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="YYYY-MM-DD"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="handleQuery">
            搜索
          </el-button>
          <el-button icon="Refresh" @click="resetQuery">
            重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 操作区域 -->
    <el-card class="operation-card">
      <div class="operation-bar">
        <div class="left-operations">
          <el-button
            v-permission="['system:role:add']"
            type="primary"
            icon="Plus"
            @click="handleAdd"
          >
            新增
          </el-button>
          <el-button
            v-permission="['system:role:edit']"
            type="success"
            icon="Edit"
            :disabled="single"
            @click="handleUpdate"
          >
            修改
          </el-button>
          <el-button
            v-permission="['system:role:remove']"
            type="danger"
            icon="Delete"
            :disabled="multiple"
            @click="handleDelete"
          >
            删除
          </el-button>
          <el-button
            v-permission="['system:role:export']"
            type="warning"
            icon="Download"
            @click="handleExport"
          >
            导出
          </el-button>
        </div>
        <div class="right-operations">
          <el-tooltip content="刷新" placement="top">
            <el-button icon="Refresh" circle @click="getList" />
          </el-tooltip>
        </div>
      </div>

      <!-- 角色列表 -->
      <el-table
        v-loading="loading"
        :data="roleList"
        @selection-change="handleSelectionChange"
        @sort-change="handleSortChange"
      >
        <el-table-column type="selection" width="50" align="center" />
        <el-table-column label="角色编号" prop="roleId" width="80" />
        <el-table-column
          label="角色名称"
          prop="roleName"
          show-overflow-tooltip
          sortable="custom"
        />
        <el-table-column
          label="权限字符"
          prop="roleKey"
          show-overflow-tooltip
          sortable="custom"
        />
        <el-table-column label="显示顺序" prop="roleSort" width="100" />
        <el-table-column label="状态" align="center" width="100">
          <template #default="{ row }">
            <el-switch
              v-model="row.status"
              v-permission="['system:role:edit']"
              active-value="0"
              inactive-value="1"
              @change="handleStatusChange(row)"
            />
          </template>
        </el-table-column>
        <el-table-column
          label="创建时间"
          prop="createTime"
          width="160"
          sortable="custom"
        >
          <template #default="{ row }">
            <span>{{ parseTime(row.createTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          width="200"
          class-name="small-padding fixed-width"
        >
          <template #default="{ row }">
            <el-tooltip content="修改" placement="top" v-if="row.roleId !== 1">
              <el-button
                v-permission="['system:role:edit']"
                link
                type="primary"
                icon="Edit"
                @click="handleUpdate(row)"
              />
            </el-tooltip>
            <el-tooltip content="删除" placement="top" v-if="row.roleId !== 1">
              <el-button
                v-permission="['system:role:remove']"
                link
                type="danger"
                icon="Delete"
                @click="handleDelete(row)"
              />
            </el-tooltip>
            <el-dropdown @command="(command) => handleCommand(command, row)">
              <el-button link type="primary" icon="DArrowRight" />
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item
                    v-permission="['system:role:edit']"
                    command="handleDataScope"
                    icon="CircleCheck"
                  >
                    数据权限
                  </el-dropdown-item>
                  <el-dropdown-item
                    v-permission="['system:user:list']"
                    command="handleAuthUser"
                    icon="User"
                  >
                    分配用户
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <pagination
        v-show="total > 0"
        v-model:page="queryForm.pageNum"
        v-model:limit="queryForm.pageSize"
        :total="total"
        @pagination="getList"
      />
    </el-card>

    <!-- 添加或修改角色对话框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="500px"
      :before-close="cancel"
    >
      <el-form
        ref="roleFormRef"
        :model="roleForm"
        :rules="roleFormRules"
        label-width="100px"
      >
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="roleForm.roleName" placeholder="请输入角色名称" />
        </el-form-item>
        <el-form-item prop="roleKey">
          <template #label>
            <span>
              <el-tooltip content="控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
                <el-icon><question-filled /></el-icon>
              </el-tooltip>
              权限字符
            </span>
          </template>
          <el-input v-model="roleForm.roleKey" placeholder="请输入权限字符" />
        </el-form-item>
        <el-form-item label="角色顺序" prop="roleSort">
          <el-input-number v-model="roleForm.roleSort" controls-position="right" :min="0" />
        </el-form-item>
        <el-form-item label="状态">
          <el-radio-group v-model="roleForm.status">
            <el-radio label="0">正常</el-radio>
            <el-radio label="1">停用</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单权限">
          <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand">展开/折叠</el-checkbox>
          <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll">全选/全不选</el-checkbox>
          <el-checkbox v-model="roleForm.menuCheckStrictly" @change="handleCheckedTreeConnect">父子联动</el-checkbox>
          <el-tree
            ref="menuRef"
            class="tree-border"
            :data="menuOptions"
            show-checkbox
            node-key="id"
            :check-strictly="!roleForm.menuCheckStrictly"
            empty-text="加载中，请稍候"
            :props="{ label: 'label', children: 'children' }"
          />
        </el-form-item>
        <el-form-item label="备注">
          <el-input
            v-model="roleForm.remark"
            type="textarea"
            placeholder="请输入内容"
            :rows="3"
            maxlength="500"
            show-word-limit
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 分配角色数据权限对话框 -->
    <el-dialog v-model="openDataScope" title="分配数据权限" width="500px" append-to-body>
      <el-form :model="roleForm" label-width="80px">
        <el-form-item label="角色名称">
          <el-input v-model="roleForm.roleName" :disabled="true" />
        </el-form-item>
        <el-form-item label="权限字符">
          <el-input v-model="roleForm.roleKey" :disabled="true" />
        </el-form-item>
        <el-form-item label="权限范围">
          <el-select v-model="roleForm.dataScope" @change="dataScopeSelectChange">
            <el-option
              v-for="item in dataScopeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item v-show="roleForm.dataScope == '2'" label="数据权限">
          <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand">展开/折叠</el-checkbox>
          <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll">全选/全不选</el-checkbox>
          <el-checkbox v-model="roleForm.deptCheckStrictly" @change="handleCheckedTreeConnect">父子联动</el-checkbox>
          <el-tree
            ref="deptRef"
            class="tree-border"
            :data="deptOptions"
            show-checkbox
            default-expand-all
            node-key="id"
            :check-strictly="!roleForm.deptCheckStrictly"
            empty-text="加载中，请稍候"
            :props="{ label: 'label', children: 'children' }"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitDataScope">确 定</el-button>
          <el-button @click="cancelDataScope">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { 
  getRoleList, 
  getRole,
  addRole, 
  updateRole, 
  delRole, 
  changeRoleStatus,
  exportRole,
  dataScope as updateDataScope
} from '@/api/system/role'
import { getMenuTreeSelect, roleMenuTreeSelect } from '@/api/system/menu'
import { deptTreeSelect } from '@/api/system/user'
import { parseTime } from '@/utils/global'
import Pagination from '@/components/Pagination/index.vue'

// 遮罩层
const loading = ref(true)
// 选中数组
const ids = ref<number[]>([])
// 非单个禁用
const single = ref(true)
// 非多个禁用
const multiple = ref(true)
// 总条数
const total = ref(0)
// 角色表格数据
const roleList = ref<any[]>([])
// 弹出层标题
const dialogTitle = ref('')
// 是否显示弹出层
const dialogVisible = ref(false)
// 是否显示弹出层（数据权限）
const openDataScope = ref(false)
// 菜单列表
const menuOptions = ref<any[]>([])
// 部门列表
const deptOptions = ref<any[]>([])
// 日期范围
const dateRange = ref<string[]>([])

// 表单引用
const queryFormRef = ref<FormInstance>()
const roleFormRef = ref<FormInstance>()
const menuRef = ref()
const deptRef = ref()

// 菜单树相关
const menuExpand = ref(false)
const menuNodeAll = ref(false)
// 部门树相关
const deptExpand = ref(true)
const deptNodeAll = ref(false)

// 数据范围选项
const dataScopeOptions = ref([
  { value: '1', label: '全部数据权限' },
  { value: '2', label: '自定数据权限' },
  { value: '3', label: '本部门数据权限' },
  { value: '4', label: '本部门及以下数据权限' },
  { value: '5', label: '仅本人数据权限' },
])

// 查询参数
const queryForm = reactive({
  pageNum: 1,
  pageSize: 10,
  roleName: '',
  roleKey: '',
  status: '',
  beginTime: undefined,
  endTime: undefined,
})

// 角色表单数据
const roleForm = reactive({
  roleId: undefined,
  roleName: '',
  roleKey: '',
  roleSort: 0,
  status: '0',
  menuIds: [],
  deptIds: [],
  menuCheckStrictly: true,
  deptCheckStrictly: true,
  dataScope: '1',
  remark: '',
})

// 表单校验
const roleFormRules: FormRules = {
  roleName: [
    { required: true, message: '角色名称不能为空', trigger: 'blur' },
  ],
  roleKey: [
    { required: true, message: '权限字符不能为空', trigger: 'blur' },
  ],
  roleSort: [
    { required: true, message: '角色顺序不能为空', trigger: 'blur' },
  ],
}

// 计算属性
const computedDialogTitle = computed(() => roleForm.roleId === undefined ? '添加角色' : '修改角色')

/** 查询角色列表 */
const getList = async () => {
  loading.value = true
  try {
    const params = {
      ...queryForm,
      beginTime: dateRange.value ? dateRange.value[0] : undefined,
      endTime: dateRange.value ? dateRange.value[1] : undefined,
    }
    const { data } = await getRoleList(params)
    roleList.value = data.rows
    total.value = data.total
  } catch (error) {
    console.error('获取角色列表失败:', error)
  } finally {
    loading.value = false
  }
}

/** 查询菜单树结构 */
const getMenuTreeSelect = async () => {
  try {
    const { data } = await getMenuTreeSelect()
    menuOptions.value = data
  } catch (error) {
    console.error('获取菜单树失败:', error)
  }
}

/** 根据角色ID查询菜单树结构 */
const getRoleMenuTreeSelect = async (roleId: number) => {
  try {
    const { data } = await roleMenuTreeSelect(roleId)
    menuOptions.value = data.menus
    nextTick(() => {
      data.checkedKeys.forEach((key: number) => {
        nextTick(() => {
          menuRef.value.setChecked(key, true, false)
        })
      })
    })
  } catch (error) {
    console.error('获取角色菜单树失败:', error)
  }
}

/** 查询部门树结构 */
const getDeptTreeSelect = async () => {
  try {
    const { data } = await deptTreeSelect()
    deptOptions.value = data
  } catch (error) {
    console.error('获取部门树失败:', error)
  }
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryForm.pageNum = 1
  getList()
}

/** 重置按钮操作 */
const resetQuery = () => {
  dateRange.value = []
  queryFormRef.value?.resetFields()
  handleQuery()
}

/** 多选框选中数据 */
const handleSelectionChange = (selection: any[]) => {
  ids.value = selection.map(item => item.roleId)
  single.value = selection.length !== 1
  multiple.value = !selection.length
}

/** 排序触发事件 */
const handleSortChange = (column: any) => {
  queryForm.orderByColumn = column.prop
  queryForm.isAsc = column.order === 'ascending' ? 'asc' : 'desc'
  getList()
}

/** 新增按钮操作 */
const handleAdd = () => {
  reset()
  getMenuTreeSelect()
  dialogVisible.value = true
  dialogTitle.value = '添加角色'
}

/** 修改按钮操作 */
const handleUpdate = async (row?: any) => {
  reset()
  const roleId = row?.roleId || ids.value[0]
  
  try {
    const { data } = await getRole(roleId)
    Object.assign(roleForm, data)
    
    await getRoleMenuTreeSelect(roleId)
    dialogVisible.value = true
    dialogTitle.value = '修改角色'
  } catch (error) {
    console.error('获取角色信息失败:', error)
  }
}

/** 选择角色权限范围触发 */
const dataScopeSelectChange = (value: string) => {
  if (value !== '2') {
    deptRef.value?.setCheckedKeys([])
  }
}

/** 分配数据权限操作 */
const handleDataScope = async (row: any) => {
  reset()
  await getDeptTreeSelect()
  
  try {
    const { data } = await getRole(row.roleId)
    Object.assign(roleForm, data)
    
    openDataScope.value = true
    nextTick(() => {
      data.deptIds?.forEach((deptId: number) => {
        nextTick(() => {
          deptRef.value.setChecked(deptId, true, false)
        })
      })
    })
  } catch (error) {
    console.error('获取角色信息失败:', error)
  }
}

/** 分配用户操作 */
const handleAuthUser = (row: any) => {
  // TODO: 跳转到分配用户页面
  ElMessage.info('分配用户功能待实现')
}

/** 提交按钮（数据权限） */
const submitDataScope = async () => {
  if (roleForm.roleId !== undefined) {
    roleForm.deptIds = getDeptAllCheckedKeys()
    try {
      await updateDataScope(roleForm)
      ElMessage.success('设置成功')
      openDataScope.value = false
      getList()
    } catch (error) {
      console.error('设置数据权限失败:', error)
    }
  }
}

/** 取消按钮（数据权限） */
const cancelDataScope = () => {
  openDataScope.value = false
  reset()
}

/** 树权限（展开/折叠）*/
const handleCheckedTreeExpand = (value: boolean) => {
  if (menuRef.value) {
    const treeList = menuOptions.value
    for (let i = 0; i < treeList.length; i++) {
      menuRef.value.store.nodesMap[treeList[i].id].expanded = value
    }
  }
}

/** 树权限（全选/全不选） */
const handleCheckedTreeNodeAll = (value: boolean) => {
  if (menuRef.value) {
    menuRef.value.setCheckedNodes(value ? menuOptions.value : [])
  }
}

/** 树权限（父子联动） */
const handleCheckedTreeConnect = (value: boolean) => {
  roleForm.menuCheckStrictly = value
}

/** 所有菜单节点数据 */
const getMenuAllCheckedKeys = () => {
  // 目前被选中的菜单节点
  const checkedKeys = menuRef.value.getCheckedKeys()
  // 半选中的菜单节点
  const halfCheckedKeys = menuRef.value.getHalfCheckedKeys()
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
  return checkedKeys
}

/** 所有部门节点数据 */
const getDeptAllCheckedKeys = () => {
  // 目前被选中的部门节点
  const checkedKeys = deptRef.value.getCheckedKeys()
  // 半选中的部门节点
  const halfCheckedKeys = deptRef.value.getHalfCheckedKeys()
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
  return checkedKeys
}

/** 删除按钮操作 */
const handleDelete = async (row?: any) => {
  const roleIds = row?.roleId ? [row.roleId] : ids.value
  
  try {
    await ElMessageBox.confirm(
      `是否确认删除角色编号为"${roleIds}"的数据项？`,
      '警告',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }
    )
    
    await delRole(roleIds)
    await getList()
  } catch (error) {
    console.log('取消删除')
  }
}

/** 角色状态修改 */
const handleStatusChange = async (row: any) => {
  const text = row.status === '0' ? '启用' : '停用'
  try {
    await ElMessageBox.confirm(`确认要"${text}""${row.roleName}"角色吗？`, '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
    
    await changeRoleStatus(row.roleId, row.status)
    ElMessage.success(`${text}成功`)
  } catch (error) {
    row.status = row.status === '0' ? '1' : '0'
  }
}

/** 更多操作触发 */
const handleCommand = (command: string, row: any) => {
  switch (command) {
    case 'handleDataScope':
      handleDataScope(row)
      break
    case 'handleAuthUser':
      handleAuthUser(row)
      break
    default:
      break
  }
}

/** 导出按钮操作 */
const handleExport = async () => {
  try {
    await ElMessageBox.confirm('是否确认导出所有角色数据项？', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
    
    const params = {
      ...queryForm,
      beginTime: dateRange.value ? dateRange.value[0] : undefined,
      endTime: dateRange.value ? dateRange.value[1] : undefined,
    }
    
    await exportRole(params)
  } catch (error) {
    console.log('取消导出')
  }
}

/** 提交按钮 */
const submitForm = () => {
  roleFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      roleForm.menuIds = getMenuAllCheckedKeys()
      
      try {
        if (roleForm.roleId !== undefined) {
          await updateRole(roleForm)
        } else {
          await addRole(roleForm)
        }
        dialogVisible.value = false
        await getList()
      } catch (error) {
        console.error('提交角色信息失败:', error)
      }
    }
  })
}

/** 取消按钮 */
const cancel = () => {
  dialogVisible.value = false
  reset()
}

/** 表单重置 */
const reset = () => {
  Object.assign(roleForm, {
    roleId: undefined,
    roleName: '',
    roleKey: '',
    roleSort: 0,
    status: '0',
    menuIds: [],
    deptIds: [],
    menuCheckStrictly: true,
    deptCheckStrictly: true,
    dataScope: '1',
    remark: '',
  })
  roleFormRef.value?.resetFields()
  
  if (menuRef.value) {
    menuRef.value.setCheckedKeys([])
  }
}

// 初始化
onMounted(() => {
  getList()
})
</script>

<style lang="scss" scoped>
.role-management {
  padding: 20px;
}

.search-card,
.operation-card {
  margin-bottom: 20px;
}

.operation-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.left-operations {
  display: flex;
  gap: 8px;
}

.right-operations {
  display: flex;
  gap: 8px;
}

:deep(.el-table) {
  .el-table__cell {
    padding: 8px 0;
  }
}

.dialog-footer {
  text-align: center;
}

.tree-border {
  margin-top: 5px;
  border: 1px solid #e5e6e7;
  background: #ffffff none;
  border-radius: 4px;
  width: 100%;
}
</style>
